///@file Histogram.cpp
///@brief Implementation of an histogram
///@author Arnaud Duval
///@version 0.0
///@date 2010/05/11


#include "Histogram.h"

///@brief Default constructor
Histogram::Histogram()
{

}

///@brief Constructor with given size
///@param n Number of intervals in the histogram representation
Histogram::Histogram(unsigned int n)
{
	size = n;
	lowerbound = new double[n];
	count = new unsigned int[n];
}

///@brief Contructor from an array of realization
///@param reals Array of realizations
///@param nbr Number of realizations
///@param n Number of intervals in the histogram representation
Histogram::Histogram(double* reals, unsigned int nbr, unsigned int n)
{
	size = n;
	lowerbound = new double[n];
	count = new unsigned int[n];
	for(unsigned int i = 0 ; i < n ; i++)
		count[i] = 0;
	//Looking for min and max values of realisations
	double min, max;
	min = reals[0];
	max = reals[0];
	for(unsigned int i = 0 ; i < nbr ; i++)
	{
		if(reals[i] < min)
			min = reals[i];
		if(reals[i] > max)
			max = reals[i];
	}
	double interval_width = (max - min)/n;
	for(unsigned int i = 0 ; i < n ; i++)
	{
		lowerbound[i] = min + i*interval_width;
	}
	//Filling the histogram
	for(unsigned int i = 0 ; i < nbr ; i++)
	{
		count[(int)((reals[i] - min)/interval_width)]++;
	}

}

///@brief Constructor from a distribution
///@param d Distribution from which histogram must be computed
///@param n Number of intervals in the histogram representation
Histogram::Histogram(Distribution d, unsigned int n)
{
	size = n;
	lowerbound = new double[n];
	count = new unsigned int[n];
	for(unsigned int i = 0 ; i < n ; i++)
		count[i] = 0;
	//Looking for min and max values of realisations
	double min, max;
	min = d.Data()[0];
	max = d.Data()[0];
	for(unsigned int i = 0 ; i < d.Size() ; i++)
	{
		if(d.Data()[i] < min)
			min = d.Data()[i];
		if(d.Data()[i] > max)
			max = d.Data()[i];
	}
	double interval_width = (max - min)/n;
	for(unsigned int i = 0 ; i < n ; i++)
	{
		lowerbound[i] = min + i*interval_width;
	}
	//Filling the histogram
	for(unsigned int i = 0 ; i < d.Size() ; i++)
	{
		count[(int)((d.Data()[i] - min)/interval_width)]++;
	}
}

///@brief Copy constructor
///@param h Histogram object to copy
Histogram::Histogram(const Histogram& h)
{
	size = h.size;
	lowerbound = new double[size];
	count = new unsigned int[size];
	for(unsigned int i = 0 ; i < size ; i++)
	{
		count[i] = h.count[i];
		lowerbound[i] = h.lowerbound[i];
	}
}

///@brief Copy constructor from temporary objects
///@param h Pointer to Histogram object to copy
Histogram::Histogram(Histogram* h)
{
	size = (*h).size;
	lowerbound = new double[size];
	count = new unsigned int[size];
	for(unsigned int i = 0 ; i < size ; i++)
	{
		count[i] = (*h).count[i];
		lowerbound[i] = (*h).lowerbound[i];
	}
}

///@brief Destructor
Histogram::~Histogram()
{
	delete count;
	delete lowerbound;
}

/*		///@brief Overload of = operator
		Histogram& operator=(const Histogram&);
		///@brief Overload of = operator for temporary objects
		Histogram& operator=(Histogram*);
*/

///@brief Overload of << operator
///@param s out stream
///@param h Histogram object to put in the out stream
std::ostream& operator << (std::ostream& s, const Histogram& h)
{
	for(unsigned int i = 0 ; i < h.size ; i++)
		s << h.lowerbound[i] << "\t" << h.count[i] << "\n";
	return s;
}
